﻿/*! @file */
/*
	Copyright (C) 2008, kobake
	Copyright (C) 2018-2022, Sakura Editor Organization

	SPDX-License-Identifier: Zlib
*/
#ifndef SAKURA_CVIEWSELECT_08C2314F_EB28_43C0_9719_56EB5A6A95C5_H_
#define SAKURA_CVIEWSELECT_08C2314F_EB28_43C0_9719_56EB5A6A95C5_H_
#pragma once

class CEditView;

#include "basis/SakuraBasis.h"
#include "doc/layout/CLayout.h"

class CViewSelect{
public:
	CEditView* GetEditView(){ return m_pcEditView; }
	const CEditView* GetEditView() const{ return m_pcEditView; }

public:
	CViewSelect(CEditView* pcEditView);
	void CopySelectStatus(CViewSelect* pSelect) const;

	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
	//                      選択範囲の変更                         //
	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
	void DisableSelectArea( bool bDraw, bool bDrawBracketCursorLine = true ); //!< 現在の選択範囲を非選択状態に戻す

	void BeginSelectArea( const CLayoutPoint* po = nullptr );								// 現在のカーソル位置から選択を開始する
	void ChangeSelectAreaByCurrentCursor( const CLayoutPoint& ptCaretPos );			// 現在のカーソル位置によって選択範囲を変更
	void ChangeSelectAreaByCurrentCursorTEST( const CLayoutPoint& ptCaretPos, CLayoutRange* pSelect );// 現在のカーソル位置によって選択範囲を変更

	//!選択範囲を指定する(原点未選択)
	// 2005.06.24 Moca
	void SetSelectArea( const CLayoutRange& sRange )
	{
		m_sSelectBgn.Set(sRange.GetFrom());
		m_sSelect = sRange;
	}

	//!単語選択開始
	void SelectBeginWord()
	{
		m_bBeginSelect     = true;				/* 範囲選択中 */
		m_bBeginBoxSelect  = false;			/* 矩形範囲選択中でない */
		m_bBeginLineSelect = false;			/* 行単位選択中 */
		m_bBeginWordSelect = true;			/* 単語単位選択中 */
	}

	//!矩形選択開始
	void SelectBeginBox()
	{
		m_bBeginSelect     = true;			/* 範囲選択中 */
		m_bBeginBoxSelect  = true;		/* 矩形範囲選択中 */
		m_bBeginLineSelect = false;		/* 行単位選択中 */
		m_bBeginWordSelect = false;		/* 単語単位選択中 */
	}

	//!謎の選択開始
	void SelectBeginNazo()
	{
		m_bBeginSelect     = true;			/* 範囲選択中 */
//		m_bBeginBoxSelect  = false;		/* 矩形範囲選択中でない */
		m_bBeginLineSelect = false;		/* 行単位選択中 */
		m_bBeginWordSelect = false;		/* 単語単位選択中 */
	}

	//!範囲選択終了
	void SelectEnd()
	{
		m_bBeginSelect = false;
	}

	//!m_bBeginBoxSelectを設定。
	void SetBoxSelect(bool b)
	{
		m_bBeginBoxSelect = b;
	}

	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
	//                           描画                              //
	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
	void DrawSelectArea(bool bDrawBracketCursorLine = true);		//!< 指定行の選択領域の描画
private:
	void DrawSelectArea2(HDC) const;		//!< 指定範囲の選択領域の描画
	void DrawSelectAreaLine(			//!< 指定行の選択領域の描画
		HDC					hdc,		//!< [in] 描画領域のDevice Context Handle
		CLayoutInt			nLineNum,	//!< [in] 描画対象行(レイアウト行)
		const CLayoutRange&	sRange		//!< [in] 選択範囲(レイアウト単位)
	) const;
public:
	void GetSelectAreaLineFromRange(CLayoutRange& ret, CLayoutInt nLineNum, const CLayout* pcLayout, const CLayoutRange& sRange) const;
	void GetSelectAreaLine(CLayoutRange& ret, CLayoutInt nLineNum, const CLayout* pcLayout) const{
		GetSelectAreaLineFromRange(ret, nLineNum, pcLayout, m_sSelect);
	}
	CLayoutRange GetSelectAreaLine(CLayoutInt nLineNum, const CLayout* pcLayout) const{
		CLayoutRange ret;
		GetSelectAreaLineFromRange(ret, nLineNum, pcLayout, m_sSelect);
		return ret;
	}
	//! 選択情報データの作成	2005.07.09 genta
	void PrintSelectionInfoMsg() const;

	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
	//                         状態取得                            //
	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
	//! テキストが選択されているか
	// 2002/03/29 Azumaiya インライン関数化
	bool IsTextSelected() const
	{
		return m_sSelect.IsValid();
//		return 0!=(
//			~((DWORD)(m_sSelect.nLineFrom | m_sSelect.nLineTo | m_sSelect.nColumnFrom | m_sSelect.nColumnTo)) >> 31
//			);
	}

	//! テキストの選択中か
	// 2002/03/29 Azumaiya インライン関数化
	bool IsTextSelecting() const
	{
		// ジャンプ回数を減らして、一気に判定。
		return m_bSelectingLock || IsTextSelected();
	}

	//!マウスで選択中か
	bool IsMouseSelecting() const
	{
		return m_bBeginSelect;
	}

	//!矩形選択中か
	bool IsBoxSelecting() const
	{
		return m_bBeginBoxSelect;
	}

private:
	//参照
	CEditView*	m_pcEditView;

public:

	bool	m_bDrawSelectArea;		// 選択範囲を描画したか	// 02/12/13 ai

	// 選択状態
	bool	m_bSelectingLock;		// 選択状態のロック
private:
	bool	m_bBeginSelect;			// 範囲選択中
	bool	m_bBeginBoxSelect;		// 矩形範囲選択中
	bool	m_bSelectAreaChanging;	// 選択範囲変更中
	int		m_nLastSelectedByteLen;	// 前回選択時の選択バイト数

public:
	bool	m_bBeginLineSelect;		// 行単位選択中
	bool	m_bBeginWordSelect;		// 単語単位選択中

	// 選択範囲を保持するための変数群
	// これらはすべて折り返し行と、折り返し桁を保持している。
	CLayoutRange m_sSelectBgn; //範囲選択(原点)
	CLayoutRange m_sSelect;    //範囲選択
	CLayoutRange m_sSelectOld; //範囲選択Old

	CMyPoint	m_ptMouseRollPosOld;	// マウス範囲選択前回位置(XY座標)
};

/*
m_sSelectOldについて
	DrawSelectArea()に現在の選択範囲を教えて差分のみ描画するためのもの
	現在の選択範囲をOldへコピーした上で新しい選択範囲をSelectに設定して
	DrawSelectArea()を呼びだすことで新しい範囲が描かれる．
*/
#endif /* SAKURA_CVIEWSELECT_08C2314F_EB28_43C0_9719_56EB5A6A95C5_H_ */
